class Vue {
  constructor(obj_instance) {
    this.$data = obj_instance.data;
    Observer(this.$data);
    Compile(obj_instance.el, this);
  }
}

function Observer(data_instance) {
  if (!data_instance || typeof data_instance !== 'object') return;
  const dependency = new Dependency();
  Object.keys(data_instance).forEach((key) => {
    let value = data_instance[key];
    Observer(value);
    Object.defineProperty(data_instance, key, {
      enumerable: true,
      configurable: true,
      get() {
        Dependency.temp && dependency.addSub(Dependency.temp);
        // if (Dependency.temp) {
        //     console.log(Dependency.temp);
        // }
        console.log(`访问了属性:${key} => 值: ${value}`);
        return value;
      },
      set(newValue) {
        console.log(`属性${key}的值${value}修改为 => ${newValue}`);
        value = newValue;
        Observer(newValue);
        dependency.notify();
      },
    });
  });
}

// 拿到初始值，渲染模板，生成订阅者
function Compile(element, vm) {
  vm.$el = document.querySelector(element);
  const fragment = document.createDocumentFragment();
  let child;
  while ((child = vm.$el.firstChild)) {
    fragment.append(child);
  }
  fragment_compile(fragment);

  function fragment_compile(node) {
    const pattern = /\{\{\s*(\S+)\s*\}\}/;
    // 递归跳出条件，一次寻找文本节点并用正则匹配进行替换
    if (node.nodeType === 3) {
      let xxx = node.nodeValue;
      // 返回是否通过验证规则 和 验证的信息数组
      const result_regex = pattern.exec(node.nodeValue);
      if (result_regex) {
        // more.like 取出来转为 ['more','like']
        const arr = result_regex[1].split('.');
        // console.log(arr);
        const value = arr.reduce((total, current) => total[current], vm.$data);
        node.nodeValue = xxx.replace(pattern, value);
        // 创建订阅者
        new Watcher(vm, result_regex[1], (newValue) => {
          node.nodeValue = xxx.replace(pattern, newValue);
        });
      }
      return;
    }
    // 当为节点且为input的时候，实现 v-model 实现 视图 -> 数据的更新
    if (node.nodeType === 1 && node.nodeName === 'INPUT') {
      // 类数组转换为数组 [type, v-model]
      const attr = Array.from(node.attributes);
      console.log(attr);
      attr.forEach((i) => {
        if (i.nodeName === 'v-model') {
          const value = i.nodeValue.split('.').reduce((total, current) => total[current], vm.$data);
          node.value = value;
          new Watcher(vm, i.nodeValue, (newValue) => {
            node.value = newValue;
          });
          node.addEventListener('input', (e) => {
            // ['more','like']
            const arr1 = i.nodeValue.split('.');
            // ['more']
            const arr2 = arr1.slice(0, arr1.length - 1);
            // vm.$data.more
            const final = arr2.reduce((total, current) => total[current], vm.$data);
            // vm.$data.more['like'] = e.target.value
            final[arr1[arr1.length - 1]] = e.target.value;
          });
        }
      });
    }

    node.childNodes.forEach((child) => fragment_compile(child));
  }
  vm.$el.appendChild(fragment);
}

// 依赖 收集和通知订阅者
class Dependency {
  constructor() {
    this.subscribers = [];
  }
  // 增加订阅者
  addSub(sub) {
    this.subscribers.push(sub);
  }
  // 监听到变化，进行数据 -> 视图的更新
  notify() {
    this.subscribers.forEach((sub) => sub.update());
  }
}

// 订阅者
class Watcher {
  constructor(vm, key, callback) {
    // vue实例
    this.vm = vm;
    // 属性
    this.key = key;
    this.callback = callback;
    Dependency.temp = this;
    // console.log(`用属性 ${key} 创建订阅者`);
    // 触发Oberver的 get 使订阅者添加到 dependency 里面
    key.split('.').reduce((total, current) => total[current], vm.$data);
    Dependency.temp = null;
  }
  update() {
    let newValue = this.key.split('.').reduce((total, current) => total[current], this.vm.$data);
    this.callback(newValue);
  }
}
